# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1119  -> 1.1120 
#	  drivers/char/mem.c	1.39    -> 1.40   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/04	davidm@tiger.hpl.hp.com	1.1120
# Fix up drivers/char/mem.c some more.
# --------------------------------------------
#
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Sun Jun  8 00:40:30 2003
+++ b/drivers/char/mem.c	Sun Jun  8 00:40:30 2003
@@ -105,6 +105,39 @@
 }
 
 
+static ssize_t do_write_io(struct file * file, void *p, unsigned long realp,
+			    const char * buf, size_t count, loff_t *ppos)
+{
+	ssize_t written;
+	char byte;
+	size_t i;
+
+	/* this is slow but nobody cares... */
+
+	written = 0;
+#if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU))
+	/* we don't have page 0 mapped on sparc and m68k.. */
+	if (realp < PAGE_SIZE) {
+		unsigned long sz = PAGE_SIZE-realp;
+		if (sz > count) sz = count;
+		/* Hmm. Do something? */
+		buf+=sz;
+		p+=sz;
+		count-=sz;
+		written+=sz;
+	}
+#endif
+	for (i = 0; i < count; ++i) {
+		if (get_user(byte, buf + i))
+			return -EFAULT;
+		writeb(byte, p + i);
+	}
+	written += count;
+	*ppos += written;;
+	return written;
+}
+
+
 /*
  * This funcion reads the *physical* memory. The f_pos points directly to the 
  * memory location. 
@@ -114,7 +147,6 @@
 {
 	unsigned long p = *ppos;
 	unsigned long end_mem;
-	int uncached;
 	ssize_t read;
 	void *addr;
 
@@ -140,15 +172,22 @@
 		}
 	}
 #endif
-	uncached = uncached_access(file, (unsigned long) p);
-	if (uncached)
-		addr = ioremap(p, count);
-	else
-		addr = __va(p);
-	if (copy_to_user(buf, addr, count))
-		return -EFAULT;
-	if (uncached)
+	if (uncached_access(file, (unsigned long) p)) {
+		char byte;
+		size_t i;
+
+		if (!(addr = ioremap(p, count)))
+			return -EFAULT;
+		/* this is slow but nobody cares... */
+		for (i = 0; i < count; ++i) {
+			byte = readb(addr + i);
+			if (put_user(byte, buf + i))
+				return -EFAULT;
+		}
 		iounmap(addr);
+	} else
+		if (copy_to_user(buf, __va(p), count))
+			return -EFAULT;
 	read += count;
 	*ppos += read;
 	return read;
@@ -159,7 +198,6 @@
 {
 	unsigned long p = *ppos;
 	unsigned long end_mem;
-	int uncached;
 	ssize_t ret;
 	void *addr;
 
@@ -168,14 +206,13 @@
 		return 0;
 	if (count > end_mem - p)
 		count = end_mem - p;
-	uncached = uncached_access(file, (unsigned long) p);
-	if (uncached)
-		addr = ioremap(p, count);
-	else
-		addr = __va(p);
-	ret = do_write_mem(file, addr, p, buf, count, ppos);
-	if (uncached)
+	if (uncached_access(file, (unsigned long) p)) {
+		if (!(addr = ioremap(p, count)))
+			return -EFAULT;
+		ret = do_write_io(file, addr, p, buf, count, ppos);
 		iounmap(addr);
+	} else
+		ret = do_write_mem(file, __va(p), p, buf, count, ppos);
 	return ret;
 }